//
// Created by root on 4/29/17.
//


#include "../runner.h"

#define OP_INTEGER(_op,_x,_y,_z) Cell* arg_x = make_integer(global_scheme, _x); \
    Cell* arg_y = make_integer(global_scheme, _y); \
    Cell* ret = make_integer(global_scheme, _z); \
    Cell* r = int_##_op \
    (global_scheme, arg_x, arg_y)

#define TEST_OK  assert_true(eqn(r, ret))

//int_add
static void test_int_add() {
    OP_INTEGER(add, 1, 2, 3);
    TEST_OK;
}

//int_mul
static void test_int_mul() {
    OP_INTEGER(mul, 2, 3, 6);
    TEST_OK;
}

//int_sub
static void test_int_sub() {
    OP_INTEGER(sub, 2, 3, -1);
    TEST_OK;
}

//int_div
static void test_int_div_when_divide_exactly() {
    OP_INTEGER(div, 6, 3, 2);
    TEST_OK;
}

static void test_int_div_when_not_divide_exactly() {
    Cell* arg_x = make_integer(global_scheme, 2);
    Cell* arg_y = make_integer(global_scheme, 3);
    Cell* ret = make_fraction(global_scheme, make_integer(global_scheme, 2), make_integer(global_scheme, 3));
    Cell* r = int_div(global_scheme, arg_x, arg_y);
    assert_true(eqn(r, ret));
}

static void test_int_div_when_divided_by_zero() {
    Cell* arg_x = make_integer(global_scheme, 1);
    Cell* arg_y = make_integer(global_scheme, 0);
    Cell* r = int_div(global_scheme, arg_x, arg_y);
    assert_true(eqe(r, E_DIVISION_BY_ZERO));
}

//TODO
int main(int argc, char **argv) {
    const struct CMUnitTest tests[] = {
            /*int_add*/
            cmocka_unit_test(test_int_add),
            /*int_mul*/
            cmocka_unit_test(test_int_mul),
            /*int_sub*/
            cmocka_unit_test(test_int_sub),
            /*int_div*/
            cmocka_unit_test(test_int_div_when_divide_exactly),
            cmocka_unit_test(test_int_div_when_not_divide_exactly),
            cmocka_unit_test(test_int_div_when_divided_by_zero),
    };
    return cmocka_run_group_tests(tests, setup_scheme, teardown_scheme);
}
